package com.zj.dmsproxy.wrapper;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import com.zj.baseproxy.utils.ClassUtil;
import com.zj.dmsproxy.enums.QueryEnum;
import com.zj.dmsproxy.wrapper.condition.*;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.function.Consumer;

/**
 * 条件拼接器
 * <p>
 * 第一层如果多次用了同一个字段，会导致前面的字段会覆盖
 * 如：.eq("eid","1").ne("eid","2") 只有.ne("eid","2")生效
 * 可以使用嵌套and解决：.and(v->v.eq("eid","1").ne("eid","2"))
 *
 * @author arthur_zhou
 * @date 2023/11/2 17:06
 * @see QueryWrapper#and(Consumer)
 */
@Data
public class QueryWrapper implements IQueryWrapper {
    /**
     * 关系， and/or
     */
    private final QueryEnum queryEnum;
    /**
     * 是否包一层$and、$or
     */
    private final boolean pack;
    /**
     * 校验值是否为空。true时，空值不放入条件
     */
    private final boolean check;
    private final List<IQueryWrapper> queryList = new ArrayList<>();

    public QueryWrapper() {
        this(QueryEnum.AND, false, true);
    }

    public QueryWrapper(QueryEnum queryEnum, boolean pack, boolean check) {
        this.queryEnum = queryEnum;
        this.pack = pack;
        this.check = check;
    }

    @Override
    public Map<String, Object> toCondition() {
        if (CollectionUtil.isEmpty(queryList)) {
            return Collections.emptyMap();
        }
        if (pack) {
            List<Map<String, Object>> resultList = new ArrayList<>();
            for (IQueryWrapper wrapper : queryList) {
                Map<String, Object> conditionMap = wrapper.toCondition();
                if (MapUtil.isNotEmpty(conditionMap)) {
                    resultList.add(conditionMap);
                }
            }
            return Collections.singletonMap(queryEnum.getRelation(), resultList);
        }
        LinkedHashMap<String, Object> resultMap = new LinkedHashMap<>();
        for (IQueryWrapper wrapper : queryList) {
            Map<String, Object> conditionMap = wrapper.toCondition();
            if (MapUtil.isNotEmpty(conditionMap)) {
                resultMap.putAll(conditionMap);
            }
        }
        return resultMap;
    }

    /**
     * 等于
     *
     * @param field 字段
     * @param value 值
     * @return 自己
     */
    public QueryWrapper eq(String field, Object value) {
        if (StringUtils.isNotEmpty(field) && check(value)) {
            queryList.add(new EqualsCondition(false, field, value));
        }
        return this;
    }

    /**
     * 不等于
     *
     * @param field 字段
     * @param value 值
     * @return 自己
     */
    public QueryWrapper ne(String field, Object value) {
        if (StringUtils.isNotEmpty(field) && check(value)) {
            queryList.add(new EqualsCondition(true, field, value));
        }
        return this;
    }

    /**
     * in
     *
     * @param field  字段
     * @param values 值，类型需一致
     * @return 自己
     */
    public QueryWrapper in(String field, Object... values) {
        if (StringUtils.isNotEmpty(field) && Objects.nonNull(values) && values.length > 0) {
            return in(field, Arrays.asList(values));
        }
        return this;
    }

    /**
     * in
     *
     * @param field  字段
     * @param values 值，类型需一致
     * @return 自己
     */
    public QueryWrapper in(String field, Collection<?> values) {
        if (StringUtils.isNotEmpty(field) && check(values)) {
            queryList.add(new InCondition(false, field, values));
        }
        return this;
    }

    /**
     * not in
     *
     * @param field  字段
     * @param values 值，类型需一致
     * @return 自己
     */
    public QueryWrapper nin(String field, Object... values) {
        if (StringUtils.isNotEmpty(field) && Objects.nonNull(values) && values.length > 0) {
            return nin(field, Arrays.asList(values));
        }
        return this;
    }

    /**
     * not in
     *
     * @param field  字段
     * @param values 值，类型需一致
     * @return 自己
     */
    public QueryWrapper nin(String field, Collection<?> values) {
        if (StringUtils.isNotEmpty(field) && check(values)) {
            queryList.add(new InCondition(true, field, values));
        }
        return this;
    }

    /**
     * 大于
     *
     * @param field 字段
     * @param value 值
     * @return 自己
     */
    public QueryWrapper gt(String field, Object value) {
        if (StringUtils.isNotEmpty(field) && check(value)) {
            queryList.add(new RangeCondition(field, QueryEnum.GT, value));
        }
        return this;
    }

    /**
     * 大于等于
     *
     * @param field 字段
     * @param value 值
     * @return 自己
     */
    public QueryWrapper ge(String field, Object value) {
        if (StringUtils.isNotEmpty(field) && check(value)) {
            queryList.add(new RangeCondition(field, QueryEnum.GE, value));
        }
        return this;
    }

    /**
     * 小于
     *
     * @param field 字段
     * @param value 值
     * @return 自己
     */
    public QueryWrapper lt(String field, Object value) {
        if (StringUtils.isNotEmpty(field) && check(value)) {
            queryList.add(new RangeCondition(field, QueryEnum.LT, value));
        }
        return this;
    }

    /**
     * 小于等于
     *
     * @param field 字段
     * @param value 值
     * @return 自己
     */
    public QueryWrapper le(String field, Object value) {
        if (StringUtils.isNotEmpty(field) && check(value)) {
            queryList.add(new RangeCondition(field, QueryEnum.LE, value));
        }
        return this;
    }

    /**
     * between
     *
     * @param field   字段
     * @param geValue 大于等于值
     * @param leValue 小于等于值
     * @return 自己
     */
    public QueryWrapper between(String field, Object geValue, Object leValue) {
        if (StringUtils.isNotEmpty(field) && check(geValue) && check(leValue)) {
            queryList.add(new BetweenCondition(field, geValue, leValue));
        }
        return this;
    }

    /**
     * like
     *
     * @param field 字段
     * @param value 值
     * @return 自己
     */
    public QueryWrapper like(String field, Object value) {
        if (StringUtils.isNotEmpty(field) && check(value)) {
            queryList.add(new LikeCondition(false, field, value));
        }
        return this;
    }

    /**
     * nLike
     *
     * @param field 字段
     * @param value 值
     * @return 自己
     */
    public QueryWrapper nLike(String field, Object value) {
        if (StringUtils.isNotEmpty(field) && check(value)) {
            queryList.add(new LikeCondition(true, field, value));
        }
        return this;
    }

    /**
     * 嵌套and子条件，同一层多次调用会覆盖，
     * 用了$and 同一层不要使用其他字段，会被屏蔽
     *
     * @param consumer 子条件拼接方法
     * @return 自己
     */
    public QueryWrapper and(Consumer<QueryWrapper> consumer) {
        QueryWrapper wrapper = new QueryWrapper(QueryEnum.AND, true, this.check);
        consumer.accept(wrapper);
        if (CollectionUtil.isNotEmpty(wrapper.getQueryList())) {
            queryList.add(wrapper);
        }
        return this;
    }

    /**
     * 嵌套or子条件，同一层多次调用会覆盖
     *
     * @param consumer 子条件拼接方法
     * @return 自己
     */
    public QueryWrapper or(Consumer<QueryWrapper> consumer) {
        QueryWrapper wrapper = new QueryWrapper(QueryEnum.OR, true, this.check);
        consumer.accept(wrapper);
        if (CollectionUtil.isNotEmpty(wrapper.getQueryList())) {
            queryList.add(wrapper);
        }
        return this;
    }

    /**
     * 校验对象
     *
     * @param value 值
     * @return 自己
     */
    private boolean check(Object value) {
        // 开启校验且是null时，跳过
        if (Objects.isNull(value)) {
            return !check;
        }
        // 不是基础类型跳过
        if (!ClassUtil.isBaseType(value.getClass())) {
            return false;
        }
        return !check || !"".equals(value);
    }

    /**
     * 校验集合
     *
     * @param value 值
     * @return 自己
     */
    private <T> boolean check(Collection<T> value) {
        // 开启校验且是空时，跳过
        if (CollectionUtil.isEmpty(value)) {
            return !check;
        }
        // 集合的元素不是基础类型跳过
        return value.stream().allMatch(v -> Objects.isNull(v) || ClassUtil.isBaseType(v.getClass()));
    }
}
